package com.lantu.sys.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.lantu.common.utils.JwtUtil;
import com.lantu.common.vo.Result;
import com.lantu.sys.entity.*;
import com.lantu.sys.service.*;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;

import java.util.*;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/sendMoney")
public class SendMoneyController {

    @Autowired
    private ISendMoneyService sendMoneyService;

    @Autowired
    private IUserService userService;

    @Autowired
    private ISendMoneyStudentService sendMoneyStudentService;

    @Autowired
    private IPostService postService;

    @Autowired
    private IPostStudentService postStudentService;

    @Autowired
    private IStudentService studentService;

    @Autowired
    private JwtUtil jwtUtil;

    @PostMapping("/save")
    public Result save(@RequestBody SendMoneyDTO dto, @RequestHeader("X-Token") String token) {

        User loginUser = null;
        try {
            loginUser = jwtUtil.parseToken(token, User.class);
        } catch (Exception e) {
            e.printStackTrace();
        }
        dto.setTeacherId(loginUser.getId());

        SendMoney sendMoney = new SendMoney();
        BeanUtils.copyProperties(dto, sendMoney);

        sendMoneyService.saveOrUpdate(sendMoney);

        List<SendMoneyStudent> list = dto.getList().stream().map(i -> {
            SendMoneyStudent sendMoneyStudent = new SendMoneyStudent();
            sendMoneyStudent.setMoney(i.getMoney());
            sendMoneyStudent.setStudentId(i.getStudentId());
            sendMoneyStudent.setSendMoneyId(sendMoney.getId());
            return sendMoneyStudent;
        }).collect(Collectors.toList());

        sendMoneyStudentService.remove(new LambdaQueryWrapper<SendMoneyStudent>().eq(SendMoneyStudent::getSendMoneyId, sendMoney.getId()));
        sendMoneyStudentService.saveBatch(list);

        return Result.success(list, "保存成功");
    }

    @GetMapping("/list")
    public Result<Page<SendMoneyVO>> list(@RequestParam(value = "pageNo") Long pageNo,
                                    @RequestParam(value = "pageSize") Long pageSize) {

        Page<SendMoney> page = new Page<>(pageNo, pageSize);
        Page<SendMoneyVO> voPage = new Page<>();
        BeanUtils.copyProperties(page, voPage, "optimizeCountSql", "searchCount", "optimizeJoinOfCountSql", "records");
        voPage.setRecords(new ArrayList<>());
        sendMoneyService.page(page);
        if (CollectionUtils.isEmpty(page.getRecords())) {

            return Result.success(voPage);
        }

        Set<Integer> teacherIds = page.getRecords().stream().map(i -> i.getTeacherId()).collect(Collectors.toSet());
        List<User> users = userService.list(new LambdaQueryWrapper<User>().in(User::getId, teacherIds));
        Map<Integer, User> userMap = users.stream().collect(Collectors.toMap(i -> i.getId(), i -> i, (v0, v1) -> v0));

        Set<Integer> postIds = page.getRecords().stream().map(i -> i.getPostId()).collect(Collectors.toSet());
        List<PostStudent> postStudents = postStudentService.list(new LambdaQueryWrapper<PostStudent>().in(PostStudent::getPostId, postIds));
        Map<Integer, List<PostStudent>> postStudentsMap = postStudents.stream().collect(Collectors.groupingBy(PostStudent::getPostId));

        Set<Integer> sendMoneyIds = page.getRecords().stream().map(i -> i.getId()).collect(Collectors.toSet());
        List<SendMoneyStudent> sendMoneyStudents = sendMoneyStudentService.list(new LambdaQueryWrapper<SendMoneyStudent>().in(SendMoneyStudent::getSendMoneyId, sendMoneyIds));
        Map<Integer, List<SendMoneyStudent>> sendMoneyStudentsMap = sendMoneyStudents.stream().collect(Collectors.groupingBy(SendMoneyStudent::getSendMoneyId));

        voPage.setRecords(page.getRecords().stream().map(i -> {
            SendMoneyVO vo = new SendMoneyVO();
            BeanUtils.copyProperties(i, vo);
            List<SendMoneyStudent> sendMoneyStudentList = sendMoneyStudentsMap.get(i.getId());
            if (!CollectionUtils.isEmpty(sendMoneyStudentList)) {
                vo.setList(sendMoneyStudentList.stream().map(n -> {
                    SendMoneyStudentEntity entity = new SendMoneyStudentEntity();
                    BeanUtils.copyProperties(n, entity);
                    return entity;
                }).collect(Collectors.toList()));
                vo.setSumMoney(sendMoneyStudentList.stream().map(m -> m.getMoney()).filter(k -> null != k).reduce((v0, v1) -> v0 + v1).get());
            } else {
                vo.setSumMoney(0);
            }
            User user = userMap.get(vo.getTeacherId());
            if (null != user) {
                vo.setTeacher(user.getUsername());
            }
            List<PostStudent> postStudentList = postStudentsMap.get(vo.getPostId());
            if (!CollectionUtils.isEmpty(postStudentList)) {
                vo.setPostNum(postStudentList.size());
            } else {
                vo.setPostNum(0);
            }
            return vo;
        }).collect(Collectors.toList()));

        return Result.success(voPage);
    }

    @GetMapping("/{id}")
    public Result<SendMoneyVO> getById(@PathVariable("id") Integer id) {
        SendMoney sendMoney = sendMoneyService.getById(id);

        List<User> users = userService.list(new LambdaQueryWrapper<User>().in(User::getId, sendMoney.getTeacherId()));
        Map<Integer, User> userMap = users.stream().collect(Collectors.toMap(i -> i.getId(), i -> i, (v0, v1) -> v0));

        List<PostStudent> postStudents = postStudentService.list(new LambdaQueryWrapper<PostStudent>().in(PostStudent::getPostId, sendMoney.getPostId()));
        Map<Integer, List<PostStudent>> postStudentsMap = postStudents.stream().collect(Collectors.groupingBy(PostStudent::getPostId));

        List<SendMoneyStudent> sendMoneyStudents = sendMoneyStudentService.list(new LambdaQueryWrapper<SendMoneyStudent>().in(SendMoneyStudent::getSendMoneyId, sendMoney.getId()));
        Map<Integer, List<SendMoneyStudent>> sendMoneyStudentsMap = sendMoneyStudents.stream().collect(Collectors.groupingBy(SendMoneyStudent::getSendMoneyId));
        Set<Integer> studentIds = sendMoneyStudents.stream().map(i -> i.getStudentId()).collect(Collectors.toSet());

        List<Student> students = studentService.list(new LambdaQueryWrapper<Student>().in(Student::getId, studentIds));
        Map<Integer, Student> studentMap = students.stream().collect(Collectors.toMap(i -> i.getId(), i -> i));

        SendMoneyVO vo = new SendMoneyVO();
        BeanUtils.copyProperties(sendMoney, vo);
        List<SendMoneyStudent> sendMoneyStudentList = sendMoneyStudentsMap.get(sendMoney.getId());
        if (!CollectionUtils.isEmpty(sendMoneyStudentList)) {

            List<SendMoneyStudentEntity> sendMoneyStudentEntities = sendMoneyStudentList.stream().map(i -> {
                SendMoneyStudentEntity entity = new SendMoneyStudentEntity();
                BeanUtils.copyProperties(i, entity);
                Student student = studentMap.get(entity.getStudentId());
                if (null != student) {
                    entity.setStudent(student.getName());
                }
                return entity;
            }).collect(Collectors.toList());

            vo.setList(sendMoneyStudentEntities);
            vo.setSumMoney(sendMoneyStudentList.stream().map(m -> m.getMoney()).filter(k -> null != k).reduce((v0, v1) -> v0 + v1).get());
        } else {
            vo.setSumMoney(0);
        }
        User user = userMap.get(vo.getTeacherId());
        if (null != user) {
            vo.setTeacher(user.getUsername());
        }
        List<PostStudent> postStudentList = postStudentsMap.get(vo.getPostId());
        if (!CollectionUtils.isEmpty(postStudentList)) {
            vo.setPostNum(postStudentList.size());
        } else {
            vo.setPostNum(0);
        }

        return Result.success(vo);
    }

    @DeleteMapping("/{id}")
    public Result<Post> deleteById(@PathVariable("id") Integer id) {
        sendMoneyService.removeById(id);
        sendMoneyStudentService.remove(new LambdaQueryWrapper<SendMoneyStudent>().eq(SendMoneyStudent::getSendMoneyId, id));
        return Result.success("删除成功");
    }
}
